//
//  socketmy.swift
//  touc
//
//  Created by z on 2020/6/27.
//  Copyright © 2020 z. All rights reserved.
//

import Foundation
func str2ip(_ st:String) -> uint32 {
    let x =  st.split(separator: ".")
    var ret:uint32=0
    for i in 0...3
    {
        ret += uint32( (x[i] as NSString).integerValue)<<(8*i)
    }
    return ret
}
func ip2str(_ n:uint32)->String
{
    var l = [n%256,n/256%256,n/(256*256)%256,n/(256*256*256)%256]
    var st=""
    for i in 0...3
    {
        st+=String (l[i])
        if i != 3
        {
            st+="."
        }
    }
    return st
}
class pollKey
{
    var k = 0
    init(_ kk:Int) {
        self.k = kk
    }
    func isReadable()->Bool
    {
        return self.k&POLLIN > 0
    }
    func isWritable()->Bool
       {
           return self.k&POLLOUT > 0
       }
}
class selector
{
    var m = [Int:Int]()
    var p:Any?=nil
    func register(_ so:Int,_ e:Int)
    {
        m[so]=e
    }
    func poll(_ t:Int)->Int
    {
        p =  openPoll(Int32(m.count))
        var pollNum = 0
        for (fd,e) in m
        {
            registerPoll(p as! UnsafeMutableRawPointer, Int32(pollNum), Int32(fd), Int32(e))
            pollNum += 1
        }
        return  Int(doPoll(p as! UnsafeMutableRawPointer, Int32(pollNum), Int32(t)))
    }
    func result()->[Int:pollKey]
    {
        var re = [Int:pollKey]()
        var pollNum = 0
        for (fd,e) in m{
            var f:Int32=0
            var ee:Int32=0
            getPoll2(p as! UnsafeMutableRawPointer, Int32(pollNum), &f, &ee)
            re[Int(f)]=pollKey(Int(ee))
            pollNum += 1
        }
        return re
    }
    deinit {
        if p != nil
        {
            closePoll(p as! UnsafeMutableRawPointer)
        }
    }
}
class udpSocket {
    var mysock:Int = 0
    var buf = bytes(repeating:0,count:udpReadLen)
    init() {
        mysock = Int(makeSock(1))
    }
    init(_ n:Int) {
        mysock = n
    }
    func setblocking(_ b:Bool)
       {
           if b
           {setDoblock(Int32(mysock)) }
           else
           {  setNonblock(Int32(mysock))}
       }
    func fileno()->Int
    {
        return mysock
    }
    func sendto(_ d:inout bytes,_ add:(String,Int))
    {
        writeudp(Int32(mysock), &d, Int32(d.count),str2ip(add.0), UInt16(add.1))
    }
    func recvfrom(_ nn:Int)->(bytes,(String,Int))
    {
        var n = nn
        if n>udpReadLen
        { n = udpReadLen }
        var ip:uint32 = 0
        var port:uint16=0
        var r =  readudp_add(Int32(mysock), &buf, Int32(n), &ip, &port)
        return (bytes(buf[..<Int(r)]),(ip2str(ip),Int(port)))
    }
    func close()
    {
         closeSock(Int32(mysock))
    }
}
class tcpSocket {
    var mysock:Int = 0
    var buf = bytes(repeating:0,count:tcpReadLen)
    init() {
        mysock = Int(makeSock(0))
    }
    init(_ n:Int) {
        mysock = n
    }
    func fileno()->Int
    {
        return mysock
    }
    func bind(_ add:(String,Int))->Int
    {
        return Int(bindso(Int32(mysock), str2ip(add.0), UInt16(add.1)))
    }
    
    func listen(_ n:Int)
    {
        listenso(Int32(mysock), Int32(n))
    }
    func accept()->(tcpSocket,(String,Int))
    {
        var so = acceptso(Int32(mysock))
        var ip:uint32 = 0
        var port = getPeerAdd(so, &ip)
        return (tcpSocket(Int(so)),(ip2str(ip),Int(port)))
    }
    func getMyAdd()->(String,Int)
    {
        var ip:uint32 = 0
        var port = getAdd(Int32(mysock), &ip)
               return ((ip2str(ip),Int(port)))
    }
    func setblocking(_ b:Bool)
    {
        if b
        {setDoblock(Int32(mysock)) }
        else
        {  setNonblock(Int32(mysock))}
    }
    func setNosig()
    {
        setNoSig(Int32(mysock))
    }
    func connect(_ add:(String,Int))
    {
        connectso(Int32(mysock), str2ip(add.0), UInt16(add.1))
    }
    func close()
    {
        closeSock(Int32(mysock))
    }
    func send(_ d:inout bytes)->Int
    {
        return Int(writetcp(Int32(mysock), &d, Int32(d.count)))
    }
    func recv(_ nn:Int) ->bytes
    {
        var n = nn
        if n>tcpReadLen
        { n = tcpReadLen }
        var r =  readtcp(Int32(mysock), &buf, Int32(n))
        if r<0
        {r=0}
        return bytes(buf[..<Int(r)])
    }
}
